package com.stark.commons.spring.core.boot.config;

import java.io.IOException;
import java.net.InetAddress;

import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.floragunn.searchguard.ssl.SearchGuardSSLPlugin;
import com.floragunn.searchguard.ssl.util.SSLConfigConstants;
import com.stark.commons.spring.core.boot.properties.SearchGuardElasticsearchProperties;
import com.stark.commons.spring.core.util.Utils;

/**
 * <code>Elasticsearch</code> 整合 <code>Search Guard</code> 配置项。
 * @author Ben
 * @since 1.0.0
 * @version 1.0.0
 */
@Configuration
@ConditionalOnClass(name = {
		"org.elasticsearch.client.Client",
		"org.springframework.data.elasticsearch.client.TransportClientFactoryBean",
		"com.floragunn.searchguard.ssl.SearchGuardSSLPlugin"
})
@ConditionalOnProperty(prefix = "spring.data.elasticsearch.search-guard", name = "ssl-transport-pemcert-filepath")
@AutoConfigureBefore(name = "org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration")
@EnableConfigurationProperties(SearchGuardElasticsearchProperties.class)
public class SearchGuardElasticsearchAutoConfig {
	
	@Autowired
	private SearchGuardElasticsearchProperties properties;

	@Bean
    public TransportClient elasticsearchClient() throws NumberFormatException, IOException {
		String sslTransportPemkeyFilepath = Utils.classpath2disk(properties.getSearchGuard().getTmpDir(), properties.getSearchGuard().getSslTransportPemkeyFilepath());
		String sslTransportPemcertFilepath = Utils.classpath2disk(properties.getSearchGuard().getTmpDir(), properties.getSearchGuard().getSslTransportPemcertFilepath());
		String sslTransportPemtrustedcasFilepath = Utils.classpath2disk(properties.getSearchGuard().getTmpDir(), properties.getSearchGuard().getSslTransportPemtrustedcasFilepath());
        Settings settings = Settings.builder()
        		.put("cluster.name", properties.getClusterName())
        		.put("client.transport.sniff", properties.isClientTransportSniff())
        		.put("client.transport.ignore_cluster_name", properties.isClientIgnoreClusterName())
				.put("client.transport.ping_timeout", properties.getClientPingTimeout())
				.put("client.transport.nodes_sampler_interval", properties.getClientNodesSamplerInterval())
				.put(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_PEMKEY_FILEPATH, sslTransportPemkeyFilepath)
        		.put(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_PEMCERT_FILEPATH, sslTransportPemcertFilepath)
        		.put(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH, sslTransportPemtrustedcasFilepath)
        		.put(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_PEMKEY_PASSWORD, properties.getSearchGuard().getSslTransportPemkeyPassword())
        		.build();
        TransportClient client = new PreBuiltTransportClient(settings, SearchGuardSSLPlugin.class);
        String host, port;
        for (String node : properties.getClusterNodes().split(",")) {
        	host = StringUtils.substringBeforeLast(node, ":");
        	port = StringUtils.substringAfterLast(node, ":");
            client.addTransportAddress(new TransportAddress(InetAddress.getByName(host), Integer.valueOf(port)));
        }
        return client;
    }
	
}
